{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sales agent sending to multiple recepients"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "from agents import Agent, Runner, trace, function_tool\n",
    "from openai.types.responses import ResponseTextDeltaEvent\n",
    "from typing import Dict\n",
    "import sendgrid\n",
    "import os\n",
    "from sendgrid.helpers.mail import Mail, Email, To, Content\n",
    "import asyncio\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "load_dotenv(override=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "subject_instructions = \"You can write a subject for a cold sales email. \\\n",
    "You are given a message and you need to write a subject for an email that is likely to get a response.\"\n",
    "\n",
    "html_instructions = \"You can convert a text email body to an HTML email body. \\\n",
    "You are given a text email body which might have some markdown \\\n",
    "and you need to convert it to an HTML email body with simple, clear, compelling layout and design.\"\n",
    "\n",
    "subject_writer = Agent(name=\"Email subject writer\", instructions=subject_instructions, model=\"gpt-4o-mini\")\n",
    "subject_tool = subject_writer.as_tool(tool_name=\"subject_writer\", tool_description=\"Write a subject for a cold sales email\")\n",
    "\n",
    "html_converter = Agent(name=\"HTML email body converter\", instructions=html_instructions, model=\"gpt-4o-mini\")\n",
    "html_tool = html_converter.as_tool(tool_name=\"html_converter\",tool_description=\"Convert a text email body to an HTML email body\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "@function_tool\n",
    "def send_html_email(to_email:str, subject: str, html_body: str) -> Dict[str, str]:\n",
    "    \"\"\" Send out an email with the given subject and HTML body to all sales prospects \"\"\"\n",
    "    sg = sendgrid.SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY'))\n",
    "    from_email = Email(\"ainanihsan@gmail.com\")  # Change to your verified sender\n",
    "    to_email = To(to_email)  # Change to your recipient\n",
    "    content = Content(\"text/html\", html_body)\n",
    "    mail = Mail(from_email, to_email, subject, content).get()\n",
    "    sg.client.mail.send.post(request_body=mail)\n",
    "    return {\"status\": \"success\"}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [subject_tool, html_tool, send_html_email]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[FunctionTool(name='subject_writer', description='Write a subject for a cold sales email', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'subject_writer_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5971620>, strict_json_schema=True, is_enabled=True),\n",
       " FunctionTool(name='html_converter', description='Convert a text email body to an HTML email body', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'html_converter_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5971760>, strict_json_schema=True, is_enabled=True),\n",
       " FunctionTool(name='send_html_email', description='Send out an email with the given subject and HTML body to all sales prospects', params_json_schema={'properties': {'to_email': {'title': 'To Email', 'type': 'string'}, 'subject': {'title': 'Subject', 'type': 'string'}, 'html_body': {'title': 'Html Body', 'type': 'string'}}, 'required': ['to_email', 'subject', 'html_body'], 'title': 'send_html_email_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5971440>, strict_json_schema=True, is_enabled=True)]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "instructions = \"\"\"\n",
    "You are an Email Manager at ComplAI.\n",
    "\n",
    "Your responsibilities:\n",
    "1. Receive a single email template (body) with placeholders like {first_name}, {company}, etc.\n",
    "2. Receive a list of recipients in the input, under the key 'recipients'. Each recipient is a dictionary with keys matching the placeholders (e.g., first_name, company, email).\n",
    "3. For each recipient:\n",
    "   a. Fill in the placeholders in the body.\n",
    "   b. Use the subject_writer tool to generate a subject for the email.\n",
    "   c. Use the html_converter tool to convert the body to HTML.\n",
    "   d. Use the send_html_email tool to send the email with the personalized subject and HTML body, passing the recipient's email as the 'to_email' argument.\n",
    "4. Return a summary with:\n",
    "   - Number of emails successfully sent\n",
    "   - Number of failures, if any\n",
    "\"\"\"\n",
    "\n",
    "emailer_agent = Agent(\n",
    "    name=\"Email Manager\",\n",
    "    instructions=instructions,\n",
    "    tools=[subject_tool, html_tool, send_html_email],  # only the tools needed\n",
    "    model=\"gpt-4o-mini\",\n",
    "    handoff_description=\"Send personalized emails to multiple recipients\"\n",
    ")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "instructions1 = \"You are a sales agent working for ComplAI, \\\n",
    "a company that provides a SaaS tool for ensuring SOC2 compliance and preparing for audits, powered by AI. \\\n",
    "You write professional, serious cold emails.\"\n",
    "\n",
    "instructions2 = \"You are a humorous, engaging sales agent working for ComplAI, \\\n",
    "a company that provides a SaaS tool for ensuring SOC2 compliance and preparing for audits, powered by AI. \\\n",
    "You write witty, engaging cold emails that are likely to get a response.\"\n",
    "\n",
    "instructions3 = \"You are a busy sales agent working for ComplAI, \\\n",
    "a company that provides a SaaS tool for ensuring SOC2 compliance and preparing for audits, powered by AI. \\\n",
    "You write concise, to the point cold emails.\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "sales_agent1 = Agent(\n",
    "        name=\"Professional Sales Agent\",\n",
    "        instructions=instructions1,\n",
    "        model=\"gpt-4o-mini\",\n",
    ")\n",
    "\n",
    "sales_agent2 = Agent(\n",
    "        name=\"Engaging Sales Agent\",\n",
    "        instructions=instructions2,\n",
    "        model=\"gpt-4o-mini\",\n",
    ")\n",
    "\n",
    "sales_agent3 = Agent(\n",
    "        name=\"Busy Sales Agent\",\n",
    "        instructions=instructions3,\n",
    "        model=\"gpt-4o-mini\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "description = \"Write a cold sales email\"\n",
    "\n",
    "tool1 = sales_agent1.as_tool(tool_name=\"sales_agent1\", tool_description=description)\n",
    "tool2 = sales_agent2.as_tool(tool_name=\"sales_agent2\", tool_description=description)\n",
    "tool3 = sales_agent3.as_tool(tool_name=\"sales_agent3\", tool_description=description)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Now we have 3 tools and 1 handoff"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[FunctionTool(name='sales_agent1', description='Write a cold sales email', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'sales_agent1_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5B5E840>, strict_json_schema=True, is_enabled=True), FunctionTool(name='sales_agent2', description='Write a cold sales email', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'sales_agent2_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5B5F060>, strict_json_schema=True, is_enabled=True), FunctionTool(name='sales_agent3', description='Write a cold sales email', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'sales_agent3_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5B5F600>, strict_json_schema=True, is_enabled=True)]\n",
      "[Agent(name='Email Manager', instructions=\"\\nYou are an Email Manager at ComplAI.\\n\\nYour responsibilities:\\n1. Receive a single email template (body) with placeholders like {first_name}, {company}, etc.\\n2. Receive a list of recipients in the input, under the key 'recipients'. Each recipient is a dictionary with keys matching the placeholders (e.g., first_name, company, email).\\n3. For each recipient:\\n   a. Fill in the placeholders in the body.\\n   b. Use the subject_writer tool to generate a subject for the email.\\n   c. Use the html_converter tool to convert the body to HTML.\\n   d. Use the send_html_email tool to send the email with the personalized subject and HTML body, passing the recipient's email as the 'to_email' argument.\\n4. Return a summary with:\\n   - Number of emails successfully sent\\n   - Number of failures, if any\\n\", prompt=None, handoff_description='Send personalized emails to multiple recipients', handoffs=[], model='gpt-4o-mini', model_settings=ModelSettings(temperature=None, top_p=None, frequency_penalty=None, presence_penalty=None, tool_choice=None, parallel_tool_calls=None, truncation=None, max_tokens=None, reasoning=None, metadata=None, store=None, include_usage=None, extra_query=None, extra_body=None, extra_headers=None, extra_args=None), tools=[FunctionTool(name='subject_writer', description='Write a subject for a cold sales email', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'subject_writer_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5971620>, strict_json_schema=True, is_enabled=True), FunctionTool(name='html_converter', description='Convert a text email body to an HTML email body', params_json_schema={'properties': {'input': {'title': 'Input', 'type': 'string'}}, 'required': ['input'], 'title': 'html_converter_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5971760>, strict_json_schema=True, is_enabled=True), FunctionTool(name='send_html_email', description='Send out an email with the given subject and HTML body to all sales prospects', params_json_schema={'properties': {'to_email': {'title': 'To Email', 'type': 'string'}, 'subject': {'title': 'Subject', 'type': 'string'}, 'html_body': {'title': 'Html Body', 'type': 'string'}}, 'required': ['to_email', 'subject', 'html_body'], 'title': 'send_html_email_args', 'type': 'object', 'additionalProperties': False}, on_invoke_tool=<function function_tool.<locals>._create_function_tool.<locals>._on_invoke_tool at 0x0000023FE5971440>, strict_json_schema=True, is_enabled=True)], mcp_servers=[], mcp_config={}, input_guardrails=[], output_guardrails=[], output_type=None, hooks=None, tool_use_behavior='run_llm_again', reset_tool_choice=True)]\n"
     ]
    }
   ],
   "source": [
    "tools = [tool1, tool2, tool3]\n",
    "handoffs = [emailer_agent]\n",
    "print(tools)\n",
    "print(handoffs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- UPDATED SALES MANAGER INSTRUCTIONS ---\n",
    "sales_manager_instructions = \"\"\"\n",
    "You are a Sales Manager at ComplAI. Your goal is to find the single best cold sales email using the sales_agent tools.\n",
    "\n",
    "Follow these steps carefully:\n",
    "1. Generate Drafts: Use all three sales_agent tools to generate three different email drafts.\n",
    "   - Each draft should be a **template** using placeholders like {first_name} and {company} instead of real names or emails.\n",
    "   - Do not include actual recipient names or addresses in the draft.\n",
    "2. Evaluate and Select: Review the drafts and choose the single best email template using your judgment of which one is most effective.\n",
    "   - You can use the tools multiple times if you're not satisfied with the results from the first try.\n",
    "3. Handoff for Sending: Pass ONLY the winning email template to the 'Email Manager' agent.\n",
    "   - Include the recipients list in the string you provide so the Email Manager can fill in the placeholders and send personalized emails.\n",
    "Crucial Rules:\n",
    "- You must use the sales agent tools to generate the drafts — do not write them yourself.\n",
    "- You must hand off exactly ONE email template to the Email Manager — never more than one.\n",
    "\"\"\"\n",
    "\n",
    "sales_manager = Agent(\n",
    "    name=\"Sales Manager\",\n",
    "    instructions=sales_manager_instructions,\n",
    "    tools=tools,         # list of sales agent tools\n",
    "    handoffs=handoffs,   # list containing emailer_agent\n",
    "    model=\"gpt-4o-mini\"\n",
    ")\n",
    "# Your original recipients list\n",
    "recipients = [\n",
    "    {\"first_name\": \"z\", \"company\": \"KTH\", \"email\": \"z@gmail.com\"},\n",
    "    {\"first_name\": \"a\", \"company\": \"Upwork\", \"email\": \"a@gmail.com\"},\n",
    "    {\"first_name\": \"m\", \"company\": \"RYK\", \"email\": \"m@gmail.com\"},\n",
    "\n",
    "]\n",
    "\n",
    "# Convert it to text that the agent can understand\n",
    "recipient_text = \"\\n\".join(\n",
    "    [f\"{r['first_name']} at {r['company']} <{r['email']}>\" for r in recipients]\n",
    ")\n",
    "\n",
    "# Combine the task and recipients into a single string\n",
    "message_text = f\"\"\"\n",
    "Task: Send out a cold sales email addressed to Dear CEO from Alice\n",
    "Recipients:\n",
    "{recipient_text}\n",
    "\"\"\"\n",
    "\n",
    "# --- RUN SALES MANAGER ---\n",
    "with trace(\"Automated SDR\"):\n",
    "    result = await Runner.run(sales_manager, message_text)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Remember to check the trace\n",
    "\n",
    "https://platform.openai.com/traces\n",
    "\n",
    "And then check your email!!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
